package com.example.memolaga;

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;

import com.example.memolaga.accounts.AccAdapter;
import com.example.memolaga.accounts.AccAdd;
import com.example.memolaga.accounts.AccView;
import com.example.memolaga.accounts.AccountsManager;
import com.example.memolaga.cards.CardAdapter;
import com.example.memolaga.cards.CardAdd;
import com.example.memolaga.cards.CardView;
import com.example.memolaga.cards.CardsManager;
import com.example.memolaga.credentials.CredAdd;
import com.example.memolaga.credentials.CredentialAdapter;
import com.example.memolaga.credentials.CredentialManager;
import com.example.memolaga.credentials.CredentialView;

import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;

public class MainActivity extends Activity {
	
	private static final int MENU_ADD=1, MENU_ADD_EXAMPLE=0, MENU_EXPORT=2, MENU_IMPORT=3, MENU_SETTINGS=4, MENU_ABOUT=5;
	private static final int GRP_MENU_ADD_EXAMPLE=0, SUB_MENU_CARDS_EXAMPLE=10, SUB_MENU_CREDENTIALS_EXAMPLE=11, SUB_MENU_ACCOUNTS_EXAMPLE=12;
	private static final int GRP_MENU_ADD=1, SUB_MENU_ADD_CARDS=21, SUB_MENU_ADD_CREDENTIALS=22, SUB_MENU_ADD_ACCOUNTS=23;

    private Handler timeExpiryHandler;  //Utilizzato per il tempo di scadenza dell'activity
	
	private static int REQUEST_CODE=0;

    private String key;         //La chiave di crypt AES

	private int nCred=0,nCard=0,nAcc=0;

    private int prefTimeExpiry;
	private boolean prefShowCard,prefShowCredentials,prefShowAccount;

	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
        Bundle bundle = this.getIntent().getExtras();
        if (bundle!=null)
            this.key = bundle.getString(Constants.getKeyString());
        else
            Log.i("onCreate MainActivity","sKey null");

        setContentView(R.layout.main_activity);

        this.timeExpiryHandler = new Handler();
        this.timeExpiryHandler.postDelayed(closeControls, 30 * 1000);

        //Gestione card
        CardsManager.getInstance().addCardFromFile(getFilesDir()+File.separator+Constants.getPathCardFile());


        //Gestione credenziali
        CredentialManager.getInstance().addCredFromFile(getFilesDir()+ File.separator+Constants.getPathCredentialsFile());

        //Gestione Account
        AccountsManager.getInstance().addAccFromFile(getFilesDir() + File.separator + Constants.getPathAccFile());

	}

	@Override
	protected void onResume()
	{
		super.onResume();


        this.nCard = this.getNCardsMemo();
        this.nCred = this.getNCredMemo();
        this.nAcc = this.getNAccMemo();

        //						Reload delle preferenze
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        this.prefShowCard = preferences.getBoolean(Constants.getPrefCard(), Constants.getPrefDefaultCard());
        this.prefShowCredentials = preferences.getBoolean(Constants.getPrefCredential(), Constants.getPrefDefaultCredential());
        this.prefShowAccount = preferences.getBoolean(Constants.getPrefAccount(), Constants.getPrefDefaultAccount());
        String timePref = preferences.getString(Constants.getPrefStringTimeExpiry(), "-1");

        this.prefTimeExpiry = Integer.valueOf(timePref); //TODO sistemare con int e magari inflating gui
        Log.i("PrefStringTime",timePref);
        if (this.prefTimeExpiry!=-1)
            onUserInteraction();
        else
            timeExpiryHandler.removeCallbacks(closeControls);

		this.checkIsMemo();

        this.invalidateOptionsMenu();								//	 sistemare api
	}

    @Override
	protected void onPause()
	{//Alla "terminazione" di questa attivita, questa deve essere distrutta e bisogna rifare il login
		super.onPause();
        //Log.i("MainActivity","OnPause called");

		//finish();
	}

	@Override
	protected void onStop()
	{
		super.onStop();
        Log.i("MainActivity","OnStop called");
        //Salvare i dati
        this.saveData();
		//finish();
	}

    protected void onDestroy()
    {
        super.onDestroy();
        this.saveDataAndDestroy();
    }
	
	@Override
	public void onBackPressed()
	{
		this.saveDataAndDestroy();
	}

    // Funzione richiamata al ritorno di questa activity dall'altra activity
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)		//TODO
    {
        super.onActivityResult(requestCode, resultCode, data);
		/*Log.i("onActivityResult", "Req code : " + requestCode);
		Log.i("onActivityResult", "Result code : " + resultCode);
		Log.i("onActivityResult", "Class: " + data.getClass().getName());*/
        if (resultCode==Constants.getResultEdit())
        {       //TODO
            this.reloadCard();
            this.reloadCred();
            this.reloadAcc();
        }
    }

    private void saveData()
    {
        //Save card File
        if (this.writeNewFile(Constants.getPathCardFile(), CardsManager.getInstance().getStringToWrite(CardsManager.getInstance().getCardSaved())))
            Log.i("MainActivity","Card saved");
        else
            Log.i("MainActivity","Error card saved");
        //Save cred File
        if (this.writeNewFile(Constants.getPathCredentialsFile(), CredentialManager.getInstance().getStringToWrite(CredentialManager.getInstance().getCredentialSaved())))
            Log.i("MainActivity","Credential saved");
        else
            Log.i("MainActivity","Error credential saved");
        //Save Acc File
        if (this.writeNewFile(Constants.getPathAccFile(), AccountsManager.getInstance().getStringToWrite(AccountsManager.getInstance().getAccSaved())))
            Log.i("MainActivity","Account saved");
        else
            Log.i("MainActivity","Error account saved");

    }

    private void saveDataAndDestroy()
    {
        this.saveData();
        finish();
    }

    private Runnable closeControls = new Runnable() {
        public void run() {
            saveDataAndDestroy();
            // overridePendingTransition(R.anim.fadein, R.anim.fadeout);
        }
    };

    public void onUserInteraction(){
        if (this.prefTimeExpiry!=-1){
            timeExpiryHandler.removeCallbacks(closeControls);
            timeExpiryHandler.postDelayed(closeControls, this.prefTimeExpiry * 1000);
        }
        else
            timeExpiryHandler.removeCallbacks(closeControls);
    };
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu)				//TODO fix dopo settings
	{
		// Inflate the menu; this adds items to the action bar if it is present.
		super.onCreateOptionsMenu(menu);
		SubMenu sbMenuAdd = menu.addSubMenu(Menu.NONE, MENU_ADD, 0, R.string.strMenuAdd);
		if (this.prefShowCard) sbMenuAdd.add(GRP_MENU_ADD,SUB_MENU_ADD_CARDS, 1, R.string.strCards);
		if (this.prefShowCredentials) sbMenuAdd.add(GRP_MENU_ADD,SUB_MENU_ADD_CREDENTIALS,2,R.string.strCredentials);
		if (this.prefShowAccount) sbMenuAdd.add(GRP_MENU_ADD,SUB_MENU_ADD_ACCOUNTS,3,R.string.strAccounts);
		//TODO riabiliatare quando pronta  menu.add(Menu.NONE,MENU_EXPORT,1,R.string.strMenuExport);
        // menu.add(Menu.NONE, MENU_IMPORT, 1, R.string.strMenuImport);
		SubMenu sbMenu = menu.addSubMenu(Menu.NONE, MENU_ADD_EXAMPLE, 2, R.string.strMenuAddExample);
		if (this.prefShowCard) sbMenu.add(GRP_MENU_ADD_EXAMPLE,SUB_MENU_CARDS_EXAMPLE,1,R.string.strCards);
		if (this.prefShowCredentials) sbMenu.add(GRP_MENU_ADD_EXAMPLE,SUB_MENU_CREDENTIALS_EXAMPLE,2,R.string.strCredentials);
		if (this.prefShowAccount) sbMenu.add(GRP_MENU_ADD_EXAMPLE,SUB_MENU_ACCOUNTS_EXAMPLE,3,R.string.strAccounts);
		menu.add(Menu.NONE,MENU_SETTINGS,3,R.string.strMenuSetting);
		menu.add(Menu.NONE,MENU_ABOUT,4,R.string.strMenuAbout);
		return true;
	}

    @Override
	public boolean onOptionsItemSelected(MenuItem item)			//TODO export, import
	{
		
		switch(item.getItemId())
		{
		case SUB_MENU_ADD_CARDS: {//Log.i("OnOptionsItemSelected","Menu add cards");
							Bundle bundle = new Bundle();
                            bundle.putString(Constants.getKeyString(), this.key);
							Intent intent = new Intent(MainActivity.this, CardAdd.class);
							intent.putExtras(bundle);
							startActivityForResult(intent, REQUEST_CODE);
							return true;}
		case SUB_MENU_ADD_CREDENTIALS: {//Log.i("OnOptionsItemSelected","Menu add credentials");
							Bundle bundle = new Bundle();
                            bundle.putString(Constants.getKeyString(), this.key);
							Intent intent = new Intent(MainActivity.this, CredAdd.class);
							intent.putExtras(bundle);
							startActivityForResult(intent, REQUEST_CODE);
							return true;}
		case SUB_MENU_ADD_ACCOUNTS: {Log.i("OnOptionsItemSelected","Menu add accounts");
                            Bundle bundle = new Bundle();
                            bundle.putString(Constants.getKeyString(), this.key);
                            Intent intent = new Intent(MainActivity.this, AccAdd.class);
                            intent.putExtras(bundle);
                            startActivityForResult(intent, REQUEST_CODE);
					        return true;}
		case MENU_EXPORT: {Log.i("OnOptionsItemSelected","menu export");							//TODO
		                   return true;}
        case MENU_IMPORT:{Log.i("OnOptionsItemSelected","menu import");							//TODO
                          return true;}
		case MENU_SETTINGS: {Log.i("OnOptionsItemSelected","menu settings");						
						Intent i = new Intent(MainActivity.this, SettingActivity.class);
						startActivity(i);
						return true;}
		case MENU_ABOUT: {Log.i("OnOptionsItemSelected","menu about");							
						Intent i = new Intent(MainActivity.this, AboutActivity.class);
						startActivity(i);
						return true;}
		case SUB_MENU_CARDS_EXAMPLE:{ //Log.i("OnOptionsItemSelected","sub menu cards");
                                    //onUserInteraction();    in addExampleData
									if (addExampleData(SUB_MENU_CARDS_EXAMPLE))
                                        Functions.showLongToast(getBaseContext(), getString(R.string.strOKCreateFile));
									else
                                        Functions.showLongToast(getBaseContext(), getString(R.string.strErrorCreateFile));
									return true;}
		case SUB_MENU_ACCOUNTS_EXAMPLE: {//Log.i("OnOptionsItemSelected","sub menu accounts");
                                    //onUserInteraction();      in addExampleData
									if (addExampleData(SUB_MENU_ACCOUNTS_EXAMPLE))
                                        Functions.showLongToast(getBaseContext(), getString(R.string.strOKCreateFile));
                                    else
                                        Functions.showLongToast(getBaseContext(), getString(R.string.strErrorCreateFile));
									return true;}
		case SUB_MENU_CREDENTIALS_EXAMPLE: {//Log.i("OnOptionsItemSelected","sub menu credentials");
                                    //onUserInteraction();          in addExampleData
									if (addExampleData(SUB_MENU_CREDENTIALS_EXAMPLE))
                                        Functions.showLongToast(getBaseContext(), getString(R.string.strOKCreateFile));
                                    else
                                        Functions.showLongToast(getBaseContext(), getString(R.string.strErrorCreateFile));
									return true;}
		}
		
		return super.onOptionsItemSelected(item);
	}

    @Override
	public boolean onPrepareOptionsMenu(Menu menu)			//Non usato
	{
		return super.onPrepareOptionsMenu(menu);
	}
	
	/**
	 * Funzione che ritorna il numero di cards memorizzate
	 * @return
	 */
	private int getNCardsMemo()
	{
        /*String pathFile = getFilesDir()+File.separator+Constants.getPathCardFile();
		if (new File(pathFile).exists())
			return CardsManager.getInstance(Functions.getStringOfFile(pathFile)).getNCards();
		return 0;*/
        return CardsManager.getInstance().getNCards();
	}

    private void reloadCard()
    {
        onUserInteraction();
        ListView lstCard = (ListView) findViewById(R.id.lstCard);
        CardAdapter aACards = new CardAdapter(this,CardsManager.getInstance().getCardSaved());
        lstCard.setAdapter(aACards);
        aACards.notifyDataSetChanged();
        this.checkIsMemo();
    }
	
	/**
	 * Funzione che ritorna il numero di credenziali memorizzate
	 * @return
	 */
	private int getNCredMemo()
	{
        /*String pathFile = getFilesDir()+File.separator+Constants.getPathCredentialsFile();
		if (new File(pathFile).exists())
			return CredentialManager.getInstance(Functions.getStringOfFile(pathFile)).getNCredentials();
		return 0;*/
        return CredentialManager.getInstance().getNCredentials();
	}

    private void reloadCred()
    {
        onUserInteraction();
        ListView lstCred = (ListView) findViewById(R.id.lstCred);
        CredentialAdapter aACred = new CredentialAdapter(this, CredentialManager.getInstance().getCredentialSaved());
        lstCred.setAdapter(aACred);
        aACred.notifyDataSetChanged();
        this.checkIsMemo();
    }
	
	/**
	 * Funzione che ritorna il numero di account memorizzate
	 * @return
	 */
	private int getNAccMemo()				
	{
        /*String pathFile = getFilesDir()+File.separator+Constants.getPathAccFile();
		if (new File(pathFile).exists())
			return CredentialManager.getInstance(Functions.getStringOfFile(pathFile)).getNCredentials();*/
		return AccountsManager.getInstance().getNAccounts();
	}

    private void reloadAcc()
    {
        onUserInteraction();
        ListView lstAcc = (ListView) findViewById(R.id.lstAcc);
        AccAdapter aAAcc = new AccAdapter(this, AccountsManager.getInstance().getAccSaved());
        lstAcc.setAdapter(aAAcc);
        aAAcc.notifyDataSetChanged();
        this.checkIsMemo();
    }
	
	/**
	 * Funzione per fare il check se ci sono gi� dati salvati
	 */
	private void checkIsMemo()					//TODO rivedere
	{
		Log.i("checkIsMemo nTot", String.valueOf(nCard+nAcc+nCred));
		if ((nCard+nCred+nAcc)==0) 
		{
            (findViewById(R.id.txtNoMemorizzati)).setVisibility(View.VISIBLE);
            (findViewById(R.id.layoutCred)).setVisibility(View.GONE);
            (findViewById(R.id.layoutAccount)).setVisibility(View.GONE);
            (findViewById(R.id.layoutCard)).setVisibility(View.GONE);
		}
		else
		{
            (findViewById(R.id.txtNoMemorizzati)).setVisibility(View.GONE);
			if (nCard!=0 && this.prefShowCard)
			{
                ((LinearLayout) findViewById(R.id.layoutCard)).setVisibility(View.VISIBLE);
                (findViewById(R.id.lstCard)).setVisibility(View.GONE);
                //Gestione card
                final ListView lstCard = (ListView) findViewById(R.id.lstCard);
                lstCard.setAdapter(new CardAdapter(this,CardsManager.getInstance().getCardSaved()));
                lstCard.setOnItemClickListener(new OnItemClickListener(){

                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        String s = CardsManager.getInstance().getCardIndex(position).getName();
                        Bundle bundle = new Bundle();
                        bundle.putString(Constants.getCardsName(),s);
                        bundle.putString(Constants.getKeyString(),key);
                        Intent intent = new Intent(MainActivity.this, CardView.class);
                        intent.putExtras(bundle);
                        startActivityForResult(intent, REQUEST_CODE);
                    }
                });
                ((ImageView) findViewById(R.id.expIconCard)).setImageDrawable(getResources().getDrawable(R.drawable.collapse_icon2));
                (findViewById(R.id.layoutClickCard)).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (View.GONE == lstCard.getVisibility())
                        {
                            lstCard.setVisibility(View.VISIBLE);
                            ((ImageView) findViewById(R.id.expIconCard)).setImageDrawable(getResources().getDrawable(R.drawable.expand_icon2));
                            onUserInteraction();
                        }
                        else
                        {
                            lstCard.setVisibility(View.GONE);
                            ((ImageView) findViewById(R.id.expIconCard)).setImageDrawable(getResources().getDrawable(R.drawable.collapse_icon2));
                            onUserInteraction();
                        }
                    }
                });


                //registerForContextMenu(lstCard);
                //lstCard.setOnItemLongClickListener(listener);
			}
            else
                ((LinearLayout) findViewById(R.id.layoutCard)).setVisibility(View.GONE);

			if (nCred!=0 && this.prefShowCredentials)
			{
                ((LinearLayout) findViewById(R.id.layoutCred)).setVisibility(View.VISIBLE);
				final ListView lstCred = (ListView) findViewById(R.id.lstCred);
                lstCred.setAdapter(new CredentialAdapter(this,CredentialManager.getInstance().getCredentialSaved()));
				lstCred.setOnItemClickListener(new OnItemClickListener(){

					@Override
					public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        String credName = CredentialManager.getInstance().getCredentialIndex(position).getName();
						Bundle bundle = new Bundle();
                        bundle.putString(Constants.getCardsName(),credName);
                        bundle.putString(Constants.getKeyString(),key);
						Intent intent = new Intent(MainActivity.this, CredentialView.class);
						intent.putExtras(bundle);
						startActivityForResult(intent, REQUEST_CODE);
					}
					
				});
                lstCred.setVisibility(View.GONE);
                ((ImageView) findViewById(R.id.expIconCredential)).setImageDrawable(getResources().getDrawable(R.drawable.collapse_icon2));
                LinearLayout layClickCard = (LinearLayout) findViewById(R.id.layoutClickCred);
                layClickCard.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (View.GONE == lstCred.getVisibility())
                        {
                            lstCred.setVisibility(View.VISIBLE);
                            ((ImageView) findViewById(R.id.expIconCredential)).setImageDrawable(getResources().getDrawable(R.drawable.expand_icon2));
                            onUserInteraction();
                        }
                        else
                        {
                            lstCred.setVisibility(View.GONE);
                            ((ImageView) findViewById(R.id.expIconCredential)).setImageDrawable(getResources().getDrawable(R.drawable.collapse_icon2));
                            onUserInteraction();
                        }
                    }
                });
				
				//registerForContextMenu(lstCred);
				//lstCred.setOnItemLongClickListener(listener);
			}
            else
                ((LinearLayout) findViewById(R.id.layoutCred)).setVisibility(View.GONE);

			if (nAcc!=0 && this.prefShowAccount)
			{
                ((LinearLayout) findViewById(R.id.layoutAccount)).setVisibility(View.VISIBLE);
				final ListView lstAcc = (ListView) findViewById(R.id.lstAcc);
				lstAcc.setAdapter(new AccAdapter(this, AccountsManager.getInstance().getAccSaved()));
                lstAcc.setOnItemClickListener(new OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        String accName = AccountsManager.getInstance().getAccIndex(position).getName();
                        Bundle bundle = new Bundle();
                        bundle.putString(Constants.getAccountName(),accName);
                        bundle.putString(Constants.getKeyString(),key);
                        Intent intent = new Intent(MainActivity.this, AccView.class);
                        intent.putExtras(bundle);
                        startActivityForResult(intent, REQUEST_CODE);
                    }
                });
                lstAcc.setVisibility(View.GONE);
                ((ImageView) findViewById(R.id.expIconAccount)).setImageDrawable(getResources().getDrawable(R.drawable.collapse_icon2));
                LinearLayout layClickAcc = (LinearLayout) findViewById(R.id.layoutClickAcc);
                layClickAcc.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (View.GONE == lstAcc.getVisibility())
                        {
                            lstAcc.setVisibility(View.VISIBLE);
                            ((ImageView) findViewById(R.id.expIconAccount)).setImageDrawable(getResources().getDrawable(R.drawable.expand_icon2));
                           onUserInteraction();
                        }
                        else
                        {
                            lstAcc.setVisibility(View.GONE);
                            ((ImageView) findViewById(R.id.expIconAccount)).setImageDrawable(getResources().getDrawable(R.drawable.collapse_icon2));
                            onUserInteraction();
                        }
                    }
                });

				//lstAcc.setOnItemLongClickListener(listener);
			}	
			else
                ((LinearLayout) findViewById(R.id.layoutAccount)).setVisibility(View.GONE);

		}
	}
	

	/*
	//TODO
	@Override 
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) 
    {
		super.onCreateContextMenu(menu, v, menuInfo);
		menu.setHeaderTitle(R.string.selectAction);  
        menu.add(0, v.getId(), 0, R.string.modAction);  
        menu.add(0, v.getId(), 0, R.string.delAction); 
        
    }
	
	//   http://www.nexus-lab.com/2010/11/06/dev-menu-contestuale-su-una-listview/
	 @Override  
     public boolean onContextItemSelected(MenuItem item)
     {
		 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
         if(String.valueOf(item.getTitle()).equals(getString(R.string.modAction)))
         {
        	Log.i("OnContextItemSel mod:", "id "+info.id+" info "+info.position+" targetView "+info.targetView);
         }
         else if(String.valueOf(item.getTitle()).equals(getString(R.string.delAction)))
         {
        	// Code to execute when clicked on This Item 
         }
         else
        	 return false;
         
         return true;
     }
*/
	
	//TODO   Terminare Account
	private boolean addExampleData(int i)			
	{
        onUserInteraction();
		switch (i)
		{
		case SUB_MENU_CARDS_EXAMPLE:{
            CardsManager.getInstance().cardAdd(ExampleData.getCardExample(), this.key);
            reloadCard();
			/*if (!this.writeNewFile(Constants.getPathCardFile(), CardsManager.getInstance().getStringToWrite(CardsManager.getInstance().cardAdd(ExampleData.getCardExample(), this.key)))) //TODO seed
				return false;
			else
                reloadCard();*/
			break;
			}
		case SUB_MENU_CREDENTIALS_EXAMPLE: {
            CredentialManager.getInstance().credAdd(ExampleData.getCredentialExample(), this.key);
            reloadCard();
			/*if (!this.writeNewFile(Constants.getPathCredentialsFile(), CredentialManager.getInstance().getStringToWrite(CredentialManager.getInstance().credAdd(ExampleData.getCredentialExample(), this.key)))) //TODO seed
				return false;
			else
			    reloadCred();*/
			break;
			}
		case SUB_MENU_ACCOUNTS_EXAMPLE: {
            AccountsManager.getInstance().accAdd(ExampleData.getAccountExample(), this.key);
            reloadAcc();
			break;
			}
		}
		return true;
	}

    private boolean writeNewFile(String pathFile, String toWrite)
    {
        boolean ret = true;
        Log.i("addExampleData I: ",toWrite);
        try
        {
            OutputStreamWriter osw = new OutputStreamWriter(openFileOutput(pathFile, Context.MODE_PRIVATE));
            osw.write(toWrite);
            osw.flush();
            osw.close();
        }
        catch (IOException eIO)
        {
            Log.e("addExampleData IO ",eIO.getMessage());
            ret=false;
        }
        catch (Exception e)
        {
            Log.e("addExampleData E ",e.getMessage());
            ret=false;
        }
        return ret;
    }

}
